/**
 *
 */
package com.faxsun.core.order.domain;

import com.faxsun.core.catalog.domain.FSSku;
import com.faxsun.core.order.service.type.FSInternalOrderStatus;
import com.faxsun.core.order.service.type.FSOrderStatus;
import com.faxsun.core.pricing.service.fulfillment.calculator.ShippmentFeeCalculator;
import com.faxsun.profile.core.domain.FSReferralCustomerOrderItemXref;
import com.faxsun.profile.core.domain.FSReferralCustomerOrderItemXrefImpl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.broadleafcommerce.common.currency.domain.BroadleafCurrency;
import org.broadleafcommerce.common.currency.domain.BroadleafCurrencyImpl;
import org.broadleafcommerce.common.extensibility.jpa.copy.DirectCopyTransform;
import org.broadleafcommerce.common.extensibility.jpa.copy.DirectCopyTransformMember;
import org.broadleafcommerce.common.extensibility.jpa.copy.DirectCopyTransformTypes;
import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.common.presentation.AdminPresentation;
import org.broadleafcommerce.common.presentation.AdminPresentationClass;
import org.broadleafcommerce.common.presentation.AdminPresentationToOneLookup;
import org.broadleafcommerce.common.presentation.PopulateToOneFieldsEnum;
import org.broadleafcommerce.common.presentation.client.SupportedFieldType;
import org.broadleafcommerce.common.presentation.override.AdminPresentationMergeEntry;
import org.broadleafcommerce.common.presentation.override.AdminPresentationMergeOverride;
import org.broadleafcommerce.common.presentation.override.AdminPresentationMergeOverrides;
import org.broadleafcommerce.common.presentation.override.PropertyType;
import org.broadleafcommerce.core.order.domain.GiftWrapOrderItemImpl;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.Index;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.persistence.*;
import java.math.BigDecimal;

/**
 * 添加订单商品的状态属性，用于记录退换货时的状态。仅在退货时有用.<br/>
 * 每个订单商品添加快递单号和URL<br/>
 * 添加商品原价,商品售价=海外价格*对应汇率
 * <p/>
 * 父类：GiftWrapOrderItemImpl->DiscreteOrderItemImpl->OrderItemImpl
 *
 * @author zhaoteng.song@faxsun.com
 */

@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "FS_BLC_ORDER_ITEM")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "blOrderElements")
@AdminPresentationMergeOverrides({@AdminPresentationMergeOverride(name = "",
    mergeEntries = @AdminPresentationMergeEntry(propertyType = PropertyType.AdminPresentation.READONLY, booleanOverrideValue = false))})
@AdminPresentationClass(populateToOneFields = PopulateToOneFieldsEnum.TRUE, friendlyName = "DiscreteOrderItemImpl_discreteOrderItem",
    ceilingDisplayEntity = "org.broadleafcommerce.core.order.domain.OrderItem")
@DirectCopyTransform({@DirectCopyTransformMember(templateTokens = DirectCopyTransformTypes.MULTITENANT_SITE)})
@Component
public class FSOrderItemImpl extends GiftWrapOrderItemImpl {

    @SuppressWarnings("unused")
    private static final Log LOG = LogFactory.getLog(FSOrderItemImpl.class);

    /**
     *
     */
    private static final long serialVersionUID = -3176669451057193994L;
    /**
     * 界面显示时，需要显示售价+运费
     */

    @Transient
    private static ShippmentFeeCalculator feeCalculator;
    /**
     * 订单中商品状态
     */
    @Column(name = "ORDERITEM_STATUS")
    @Index(name = "FSORDERITEM_STATUS_INDEX", columnNames = {"ORDERITEM_STATUS"})
    @AdminPresentation(friendlyName = "OrderItemImpl_Order_Status", group = "OrderItemImpl_Description", order = 1500,
        prominent = true, fieldType = SupportedFieldType.BROADLEAF_ENUMERATION,
        broadleafEnumeration = "com.faxsun.core.order.service.type.FSInternalOrderStatus", groupOrder = 1000, gridOrder = 1000)
    protected String status;
    /**
     * 境外物流信息查询网址
     */
    @Column(name = "FS_SHIPPING_URL_BROAD")
    @AdminPresentation(friendlyName = "OrderItemImpl_Sale_Shipping_QueryBroad", order = 1000, group = "Shipping_Info",
        groupOrder = 3000, tab = "快递信息", tabOrder = 6000, fieldType = SupportedFieldType.STRING)
    protected String urlBroad;
    /**
     * 境外物流信息查询单号
     */
    @Column(name = "FS_SHIPPING_REF_BROAD")
    @AdminPresentation(friendlyName = "OrderItemImpl_Sale_Shipping_ReferenceBroad", order = 2000, group = "Shipping_Info",
        groupOrder = 3000, tab = "快递信息", tabOrder = 6000, fieldType = SupportedFieldType.STRING)
    protected String shippingNumberBroad;
    /**
     * 跨境物流信息查询网址
     */
    @Column(name = "FS_SHIPPING_URL_CROSS")
    @AdminPresentation(friendlyName = "OrderItemImpl_Sale_Shipping_QueryCross", order = 3000, group = "Shipping_Info",
        groupOrder = 3000, tab = "快递信息", tabOrder = 6000, fieldType = SupportedFieldType.STRING)
    protected String urlCross;
    /**
     * 跨境物流信息查询单号
     */
    @Column(name = "FS_SHIPPING_REF_CROSS")
    @AdminPresentation(friendlyName = "OrderItemImpl_Sale_Shipping_ReferenceCross", order = 4000, group = "Shipping_Info",
        groupOrder = 3000, tab = "快递信息", tabOrder = 6000, fieldType = SupportedFieldType.STRING)
    protected String shippingNumberCross;
    /**
     * 境内物流信息查询网址
     */
    @Column(name = "FS_SHIPPING_URL_DOME")
    @AdminPresentation(friendlyName = "OrderItemImpl_Sale_Shipping_QueryDome", order = 5000, group = "Shipping_Info",
        groupOrder = 3000, tab = "快递信息", tabOrder = 6000, fieldType = SupportedFieldType.STRING)
    protected String urlDomestic;
    /**
     * 境内物流信息查询单号
     */
    @Column(name = "FS_SHIPPING_REF_DOME")
    @AdminPresentation(friendlyName = "OrderItemImpl_Sale_Shipping_ReferenceDome", order = 6000, group = "Shipping_Info",
        groupOrder = 3000, tab = "快递信息", tabOrder = 6000, fieldType = SupportedFieldType.STRING)
    protected String shippingNumberDomestic;
    /**
     * 商品海外价格
     */
    @Column(name = "FS_FOREIGN_PRICE")
    @AdminPresentation(friendlyName = "OrderItemImpl_Item_Foreign_Price", order = 4000, group = "OrderItemImpl_Pricing",
        groupOrder = 2000, fieldType = SupportedFieldType.MONEY)
    protected BigDecimal foriegnPrice;
    /**
     * 商品海外货币
     */
//	@Column(name = "FS_FOREIGN_CURRENCY")
    @AdminPresentation(friendlyName = "OrderItemImpl_Item_Foreign_Currency", order = 4000, group = "OrderItemImpl_Pricing",
        groupOrder = 2000, fieldType = SupportedFieldType.BROADLEAF_ENUMERATION,
        broadleafEnumeration = "com.faxsun.common.currency.domain.FSCurrencyEnum", readOnly = true)
    @ManyToOne(targetEntity = BroadleafCurrencyImpl.class)
    @AdminPresentationToOneLookup(lookupDisplayProperty = "friendlyName")
    protected BroadleafCurrency currencyType;
    /**
     * 外币汇率
     */
    @Column(name = "FS_CURRENCY_RATE")
    @AdminPresentation(friendlyName = "OrderItemImpl_Item_Foreign_Currency_Rate", order = 4000, group = "OrderItemImpl_Pricing",
        groupOrder = 2000, fieldType = SupportedFieldType.MONEY)
    protected BigDecimal currencyRate;
    /**
     * 商品是否可退货
     */
    @Transient
    protected boolean isCancelable = false;
    /**
     * 订单商品推荐者
     */
    @OneToOne(targetEntity = FSReferralCustomerOrderItemXrefImpl.class, mappedBy = "orderItem", optional = true,
        cascade = CascadeType.ALL, orphanRemoval = true)
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "blOrderElements")
    @AdminPresentation(friendlyName = "OrderItemImpl_ReferralCustomer", excluded = true)
    protected FSReferralCustomerOrderItemXref referralCustomerOrderItemXref;

    public FSInternalOrderStatus getStatus() {
        return FSInternalOrderStatus.getInstance(status);
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public boolean isCancelable() {
        return getIsCancelable();
    }

    public boolean getIsCancelable() {
        if (!order.getStatus().equals(FSOrderStatus.SINGED)) {
            isCancelable = false;
        } else {
            FSInternalOrderStatus s = getStatus();
            FSOrderImpl parentOrder = (FSOrderImpl) order;
            // FIXME:订单可取消且当前商品未发生退货，若有多个商品只退货部分，然后又退货，系统界面上会不允许该种操作
            isCancelable = parentOrder.isCancellable() && s == null;
        }
        return isCancelable;
    }

    /**
     * True,允许在界面显示退货状态，false为不显示
     *
     * @return
     */
    public boolean getShowStatus() {
        return status != null;
    }

    public String getUrlBroad() {
        return urlBroad;
    }

    public void setUrlBroad(String urlBroad) {
        this.urlBroad = urlBroad;
    }

    public String getShippingNumberBroad() {
        return shippingNumberBroad;
    }

    public void setShippingNumberBroad(String shippingNumberBroad) {
        this.shippingNumberBroad = shippingNumberBroad;
    }

    public String getUrlCross() {
        return urlCross;
    }

    public void setUrlCross(String urlCross) {
        this.urlCross = urlCross;
    }

    public String getShippingNumberCross() {
        return shippingNumberCross;
    }

    public void setShippingNumberCross(String shippingNumberCross) {
        this.shippingNumberCross = shippingNumberCross;
    }

    public String getUrlDomestic() {
        return urlDomestic;
    }

    public void setUrlDomestic(String urlDomestic) {
        this.urlDomestic = urlDomestic;
    }

    public String getShippingNumberDomestic() {
        return shippingNumberDomestic;
    }

    public void setShippingNumberDomestic(String shippingNumberDomestic) {
        this.shippingNumberDomestic = shippingNumberDomestic;
    }

    public BroadleafCurrency getCurrencyType() {
        return currencyType;
    }

    public void setCurrencyType(BroadleafCurrency currencyType) {
        this.currencyType = currencyType;
    }

    public BigDecimal getCurrencyRate() {
        return currencyRate;
    }

    public void setCurrencyRate(BigDecimal currencyRate) {
        this.currencyRate = currencyRate;
    }

    public BigDecimal getForiegnPrice() {
        return foriegnPrice;
    }

    public void setForiegnPrice(BigDecimal foriegnPrice) {
        this.foriegnPrice = foriegnPrice;
    }

    public Money getCalculatedShippmentFee() {
        return feeCalculator.calculateShippmentFeeBySku((FSSku) this.sku, this.quantity);
    }

    public Money getSingleCalculatedShippmentFee() {
        return feeCalculator.calculateShippmentFeeBySku((FSSku) this.sku, 1);
    }

    /**
     * 获取显示价格，售价+运费
     * 新需求：界面显示售价为实际售价+运费
     *
     * @return 售价+运费
     */
    public Money getDisplayedTotalPrice() {
        return this.getTotalPrice().add(getCalculatedShippmentFee());
    }

    public ShippmentFeeCalculator getFeeCalculator() {
        return feeCalculator;
    }

    @Autowired
    public void setFeeCalculator(ShippmentFeeCalculator feeCalculator) {
        FSOrderItemImpl.feeCalculator = feeCalculator;
    }

    @PostConstruct
    public void init() {
        getFeeCalculator();
    }

    /**
     * 显示优惠价格（实际为运费按重量计，导致总价!=（单价+运费）*数量）
     *
     * @return
     */
    public Money getDisplayedDiscount() {
        Money total = this.getPrice().add(getSingleCalculatedShippmentFee()).multiply(new BigDecimal(quantity));
        return total.subtract(this.getTotalPrice().add(getCalculatedShippmentFee()));
    }

    public FSReferralCustomerOrderItemXref getReferralCustomerOrderItemXref() {
        return referralCustomerOrderItemXref;
    }

    public void setReferralCustomerOrderItemXref(FSReferralCustomerOrderItemXref referralCustomerOrderItemXref) {
        this.referralCustomerOrderItemXref = referralCustomerOrderItemXref;
    }
}
